package com.zxjbyte.yiyi.framework.web.handler;

import cn.hutool.core.util.StrUtil;
import com.zxjbyte.yiyi.framework.common.domain.api.R;
import com.zxjbyte.yiyi.framework.common.domain.api.ResultCode;
import com.zxjbyte.yiyi.framework.common.exception.ServiceException;
import com.zxjbyte.yiyi.framework.web.config.WebProperties;
import com.zxjbyte.yiyi.framework.web.publisher.ErrorLogPublisher;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.Servlet;
import javax.servlet.http.HttpServletResponse;

/**
 * 未知异常转译和发送，方便监听，对未知异常统一处理。Order 排序优先级低
 * @Author zhangxingjia
 * @Date 2023/3/7 17:25
 * @Version: 1.0
 */
@Slf4j
@Order
@RequiredArgsConstructor
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) //servlet运行环境生效
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
@RestControllerAdvice
public class YiyiGlobalExceptionHandler {

    private final WebProperties properties;


    @ExceptionHandler(ServiceException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R<Void> handleError(ServiceException ex) {
        log.error("[ServiceException]", ex);
        return R.fail(ex.getResultCode(), ex.getMessage());
    }

    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R<Void> handleError(Throwable ex, HttpServletResponse response) {
        log.error("[java.lang.Throwable]", ex);
        if(properties.getErrorLog().getEnabled()){
            // 记录异常日志
            ErrorLogPublisher.publishEvent(ex);
        }
        if("text/event-stream".equals(response.getContentType())){
            return null;
        }
        return R.fail(ResultCode.INTERNAL_SERVER_ERROR, StrUtil.isEmpty(ex.getMessage()) ? ResultCode.INTERNAL_SERVER_ERROR.getMessage() : ex.getMessage());
    }
}
